/*
 * Copyrights of MYeBills. Do not copy or distribute without permissions.
 *
 * TODO
 */
/*
 AMENDMENTS:
 DATE          NAME        VERSION     DESCRIPTION
--------       -----       -------     -----------
 18/04/2013    MKANG       	1.0.0       1.CheckCSRUserLogonAction.java : Authenticate login user.
*/

package com.mbbmap.security.action;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Properties;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;



import com.mbbmap.app.dao.SysLogDao;
import com.mbbmap.app.exception.LogonException;
import com.mbbmap.app.home.ParamHome;
import com.mbbmap.app.home.SecAccessHome;
import com.mbbmap.app.home.SecUsersHome;
import com.mbbmap.app.home.SysLogHome;
import com.mbbmap.app.manager.ConfigManager;
import com.mbbmap.app.manager.SystemLogManager;
import com.mbbmap.security.dao.*;
import com.mbbmap.util.Constants;
/**
 *
 * Validate User Logon action
 *
 * Session Attributes upon logon:
 * -------------------------------
 * Constants.LOGINID - logon user id
 * Constants.LOGON_USER_ROLE - logon user role code
 * Constants.SEC_USER_OBJ - logon security user object
 * Constants.VISIT_STATUS - current visit status
 * Constants.LOGON_ACCESS_LIST - logon access ArrayList
 * Constants.LOGON_ERR_MSG - Error Message if any
 * Constants.LAST_LOGON_DATETIME - last accessed date time
 * Constants.MERCHANT_KEY - merchant name
 * Constants.PROPERTIES_PARAMETER - parameter properties
 * Constants.ENCRYPTION_PASSPHRASE_KEY - encryption key
 */

public final class CheckUserLogonAction extends CommonDispatchAction {
	
	public ActionForward homePage(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception { 
		HttpSession session = request.getSession(false);
		//check the user session, if the session is expire, it should lead user to timeout.
		// if havent timeout, user can continue operate
		SecUserDao oSecUserDao = (SecUserDao) session.getAttribute(Constants.LOGGED_USER);
		String strFwd = "";
		if (oSecUserDao == null){
			strFwd="sessionError";
		}else{
			strFwd=Constants.KEY_ACTION_SUCCESS;		  
		}
//		if(!isTokenValid(request)){
//			System.out.println("Token validation failed!");
//			session.invalidate();
//			return mapping.findForward(Constants.KEY_ACTION_SESSION_ERR);
//		}else{
//			resetToken(request);
//			System.out.println("Token validation passed!");
//		}

		return mapping.findForward(strFwd);

	}	
	

  public ActionForward init(ActionMapping mapping,
    ActionForm form, HttpServletRequest request,
    HttpServletResponse response) throws Exception {

	  
	SystemLogManager sysLogMgr;
	sysLogMgr = SystemLogManager.getInstance();

    final String PROG_ID="CheckUserLogonAction.init";

    System.out.println(PROG_ID + " : BEGIN");
    HttpSession session = request.getSession(false);

	//System.out.println("CheckPayeeLogonAction: Trace Speed 00" + now);
	String remoteIPaddr = request.getRemoteAddr();
	String remoteHostName = request.getRemoteHost();
	
	//check session condition

	if (session == null){
			
			return mapping.findForward(Constants.KEY_ACTION_SESSION_ERR);
	}
	

	// browser javasript is not enable
	if (request.getParameter(Constants.PARAM_JS_ENABLE) != null && request.getParameter(Constants.PARAM_JS_ENABLE).equals("no") ) {
	    String actionMsg = ConfigManager.getInstance().get(Constants.MSG_ERROR_JAVASCRIPT_NOT_ENABLE);
	    session.setAttribute(Constants.LOGON_ERR_MSG, actionMsg);
	    if (DEBUG) System.out.println("... Javascript not enable");
	    return mapping.findForward(Constants.KEY_ACTION_MAPPING_NOSCRIPT);
	}
	sysLogMgr.logMsg("CheckUserLogonAction.init() remoteIPaddr=" + remoteIPaddr);
	sysLogMgr.logMsg("CheckUserLogonAction.init() remoteHostName=" + remoteHostName);
	String sessionstatus = (String) session.getAttribute(Constants.VISIT_STATUS);
	
	//System.out.println("CheckCSRUserLogonAction.java: Trace Speed sessionstatus:" + sessionstatus);
	if (sessionstatus != null){
	    if (DEBUG) System.out.println("sessionstatus !=null");
		if ((sessionstatus.equals(Constants.VISIT_STATUS_VISITED)) || (session.isNew())){
			//This is from refresh button.. set session expires.
		    if (DEBUG) System.out.println("sessionstatus !=null 2");
  		    String errMsg = ConfigManager.getInstance().get(Constants.MSG_LOGON_ERR_LOGOUT_ACTIVE_SESSION);
  		    session.setAttribute(Constants.LOGON_ERR_MSG, errMsg);
			return mapping.findForward(Constants.KEY_ACTION_LOGOUT);

		}
	
	}
	

	// Next page to go
	String nextPage = null;
	String strErrLogonMsg = "";
	SecUserDao secUserDao;
	ArrayList secGroupAccessList = new ArrayList();

	DateFormat timeFormat = new SimpleDateFormat("hh:mm:ss");
	SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
	SimpleDateFormat dateFormat2 = new SimpleDateFormat("kk:mm:ss");
	SimpleDateFormat lastLogonDateFormat = new SimpleDateFormat("EEEE");
	SimpleDateFormat lastLogonDate2Format = new SimpleDateFormat("dd MMMM yyyy");

	String strMerchant = (String) session.getAttribute(Constants.MERCHANT_KEY);
	Properties paramProp = (Properties) session.getAttribute(Constants.PROPERTIES_PARAMETER);
	SysLogDao sysLogDao = new SysLogDao();
	
	if (strMerchant == null || paramProp == null) {
		
		  String errMsg = ConfigManager.getInstance().get(Constants.MSG_LOGON_ERR_LOGOUT_ACTIVE_SESSION);
  		  session.setAttribute(Constants.LOGON_ERR_MSG, errMsg);
  		  return mapping.findForward("sessionError");
	}
	
	int curTotalWebUserConn = 1;
	String strTmp = (String) session.getAttribute("eremitsessioncount");
	curTotalWebUserConn = Constants.CUR_WEB_CONN;
	String strPwdRegExp = (String) paramProp.getProperty(ParamHome.TECH_PARAM_PASSWORD_REG_EXPR);
	session.setAttribute(Constants.PASSWORD_REG_EXP, strPwdRegExp);
	
    try{

        int userIdMinLength = Integer.parseInt(paramProp.getProperty(ParamHome.SEC_UID_MIN_LEN));
        int userIdMaxLength = Integer.parseInt(paramProp.getProperty(ParamHome.SEC_UID_MAX_LEN));
        int userPwdMinLength = Integer.parseInt(paramProp.getProperty(ParamHome.SEC_UserPwdMinLen));
        int userPwdMaxLength = Integer.parseInt(paramProp.getProperty(ParamHome.SEC_UserPwdMaxLen));
        
		//Added By Michael 20091224: Requested by Chai to add checking for maximum web user connections
        int maxWebConnAllowed = Integer.parseInt((paramProp.getProperty(ParamHome.SEC_MAX_WEB_CON)).trim());
		if (DEBUG) System.out.println("... user id is blank maxWebConnAllowed=" + maxWebConnAllowed);
		
		String strUserID = sanitizePwd(request.getParameter(Constants.PARAM_USER_ID));
		String strUserPWD = sanitizePwd(request.getParameter(Constants.PARAM_USER_PWD));
	    sysLogMgr.logMsg("CheckUserLogonAction.init() Step 00 strUserID=" + strUserID);
	    sysLogMgr.logMsg("CheckUserLogonAction.init() Step 00 strUserPWD=" + strUserPWD);

		// Activity log
		sysLogDao.setActivityCode(Constants.ACT_CODE_LOGIN);
		sysLogDao.setAcctID(Constants.APP_MERCHANT);
		sysLogDao.setActivityName(PROG_ID);
		sysLogDao.setStatus(Constants.ACT_STATUS_FAIL_GENERAL);
		sysLogDao.setUserID(strUserID);
		sysLogDao.setUserField1(remoteIPaddr + " / " + remoteHostName);

		//if (DEBUG) System.out.println("... Merchant" + strMerchant);

		// check user id min and max length
		if ((strUserID == null) || (strUserID.equals(""))){
			nextPage = Constants.KEY_ACTION_ERR_LOGON;
			if (DEBUG) System.out.println("... user id is blank");
		}else{
			if (strUserID.length() < userIdMinLength || strUserID.length() > userIdMaxLength) {
				nextPage = Constants.KEY_ACTION_ERR_LOGON;
				if (DEBUG) System.out.println("... Invalid user id length. length=" + strUserID.length());
			}
		}

		//check user password min and max length
		if ((strUserPWD == null) || (strUserPWD.equals(""))){
			nextPage = Constants.KEY_ACTION_ERR_LOGON;
			if (DEBUG) System.out.println("... user password is blank");
		}else{
			if (strUserPWD.length() < 8 || strUserPWD.length() > 13 ) {
				nextPage = Constants.KEY_ACTION_ERR_LOGON;
				if (DEBUG) System.out.println("... Invalid user password length. The length should not less than 8 or more than 13 characters ");
			}
		}

		// TODO : check regex

		// LOGON
		try {

		    SecUsersHome suh = SecUsersHome.getInstance();
			sysLogMgr.logMsg("CheckUserLogonAction.init() Step 01 strUserID=[" + strUserID + "]-Start UpdateDormantUser");
			// Check dormant user
			//suh.updateDormantUser(strMerchant, strUserID);

			// Logon
			sysLogMgr.logMsg("CheckUserLogonAction.init() Step 02 strUserID=[" + strUserID + "]-Start Login");
			secUserDao = suh.login(strMerchant, strUserID, strUserPWD, remoteIPaddr + " / " + remoteHostName, paramProp);
			secUserDao = suh.login(strMerchant, strUserID, strUserPWD, remoteIPaddr + " / " + remoteHostName);
			
			if(secUserDao!=null){
				System.out.println("secUserDao.getCountryCode=" + secUserDao.getCountryCode());
				sysLogMgr.logMsg("CheckUserLogonAction.init() Step 06 strUserID=[" + strUserID + "]-Start Update Last Login");
				
				
				if (DEBUG) System.out.println("SecUserDao logonid=" + secUserDao.getLogonId());
				String strUserRole = secUserDao.getGroupCode();
				sysLogDao.setRole(strUserRole);
				
				//Constants.LOGON_ACCESS_LIST
				sysLogMgr.logMsg("CheckUserLogonAction.init() Step 07 strUserID=[" + strUserID + "]-Start findSecGroupAccessList");
				secGroupAccessList = SecAccessHome.getInstance().findSecGroupAccessList(strMerchant, strUserRole);
			
				System.out.println("SecUserDao logonid=" + secUserDao.getLogonId());
				strUserRole= secUserDao.getGroupCode();
				System.out.println("SecUserDao getGroupCode=" + secUserDao.getGroupCode());
				sysLogDao.setRole(strUserRole);
				session.setAttribute(Constants.LOGINID, strUserID);
				session.setAttribute(Constants.LOGON_USER_ROLE, strUserRole);
				session.setAttribute(Constants.SEC_USER_OBJ,secUserDao);
				session.setAttribute(Constants.LOGGED_USER,secUserDao);
				session.setAttribute(Constants.LAST_LOGON_DATETIME,secUserDao.getLastLoginDateTime());
				session.setAttribute(Constants.LOGON_ACCESS_LIST, secGroupAccessList);
				nextPage = Constants.KEY_ACTION_SUCCESS;			
				
				// Generate a random number 0...9 to get a random encryption passphrase
				//Random rand = new Random();
				//int randomKey = rand.nextInt(10);
				// Generate a unique encryption passphrase base on current timestamp
				Date now = new Date();
				String encryKey = ConfigManager.getInstance().get(Constants.ENCRYPTION_PASSPHRASE);
				encryKey = encryKey + now.getTime();
				session.setAttribute(Constants.ENCRYPTION_PASSPHRASE_KEY, encryKey);
				}
			
			else{
				request.setAttribute(Constants.LOGON_ERR_MSG, "INVALID USER / PASSWORD");
				nextPage = Constants.KEY_ACTION_ERR_LOGON;			
			}

		} catch (LogonException le) {
				nextPage = Constants.KEY_ACTION_ERR_LOGON;
				System.out.println("LogonException Code:"+le.getErrorCode()+":"+strErrLogonMsg);
				short code = le.getErrorCode(); 
				if (code == LogonException.INVALID_USER_ID || code == LogonException.INVALID_USER_PWD)
					strErrLogonMsg = "INVALID USER / PASSWORD";
				if (code == LogonException.USER_DISABLED)
					strErrLogonMsg = "USER IS DISABLED";
				if (code == LogonException.USER_LOCKED)
					strErrLogonMsg = "USER IS LOCKED";
				if (code == LogonException.TOO_MANY_BAD_ATTEMPTS)
					strErrLogonMsg = "TOO MANY BAD ATTEMPTS";
				if (code == LogonException.INACTIVE_USER)
					strErrLogonMsg = "INACTIVE_USER";
				if (code == LogonException.NO_ACCESS_DATE)
					strErrLogonMsg = "USER HAS NO ACCESS TO THIS DATE";
				if (code == LogonException.USER_STATUS_NOT_APPROVED)
					strErrLogonMsg = "USER STATUS IS NOT APPROVED";
				
				if (code == LogonException.CHANGE_PWD_FIRST_LOGON){
					
					SecUserDao userDao = SecUsersHome.getInstance().login(strMerchant, strUserID, strUserPWD, remoteIPaddr + " / " + remoteHostName);
					session.setAttribute(Constants.LOGGED_USER,userDao);
					session.setAttribute(Constants.SEC_USER_OBJ,userDao);
					session.setAttribute(Constants.LOGON_ACCESS_LIST, secGroupAccessList);
					
					request.setAttribute("msg", "INITIAL LOGIN, PLEASE CHANGE YOUR PASSWORD.");
					strErrLogonMsg = "INITIAL LOGIN, PLEASE CHANGE YOUR PASSWORD,";
					nextPage = Constants.KEY_ACTION_CHANGE_PWD;
				}
				if (code == LogonException.CHANGE_PWD_EXP){
					SecUserDao userDao = SecUsersHome.getInstance().login(strMerchant, strUserID, strUserPWD, remoteIPaddr + " / " + remoteHostName);
					session.setAttribute(Constants.LOGGED_USER,userDao);
					session.setAttribute(Constants.SEC_USER_OBJ,userDao);
					session.setAttribute(Constants.LOGON_ACCESS_LIST, secGroupAccessList);
					request.setAttribute("msg", "PASSWORD EXPIRED, PLEASE CHANGE YOUR PASSWORD.");
					strErrLogonMsg = "PASSWORD EXPIRED, PLEASE CHANGE YOUR PASSWORD.";
					nextPage = Constants.KEY_ACTION_CHANGE_PWD;
				}
				if (code == LogonException.IMPROPER_LOGOUT){
					strErrLogonMsg = "USER IS LOGGED IN OR IMPROPER LOGOUT";
				}
				
			sysLogMgr.logMsg("CheckUserLogonAction.init() Step 11 strUserID=[" + strUserID + "]-LogonErrMsg=" + strErrLogonMsg + " nextPage=" + nextPage);
		    request.setAttribute(Constants.LOGON_ERR_MSG, strErrLogonMsg);
			sysLogDao.setStatus(Constants.ACT_STATUS_FAIL_GENERAL);
			sysLogDao.setUserField1("LogonException Code: " + le.getErrorCode());
			sysLogDao.setUserField2(strErrLogonMsg);
			sysLogMgr.logMsg("CheckUserLogonAction.init() Step 12 strUserID=[" + strUserID + "]-SysLogHome.getInstance().insertSysLog(sysLogDao);");
			SysLogHome.getInstance().insertSysLog(sysLogDao);

		}

	}catch (Exception e1) {
		sysLogDao.setStatus(Constants.ACT_STATUS_FAIL_GENERAL);
		sysLogDao.setUserField1("Exception : " + e1.getMessage());
		SysLogHome.getInstance().insertSysLog(sysLogDao);

	    System.out.println("Exception: " + e1.toString());
		e1.printStackTrace();
		return mapping.findForward(Constants.KEY_ACTION_MAPPING_ERR);
	}catch (Throwable e2) {
		sysLogDao.setStatus(Constants.ACT_STATUS_FAIL_GENERAL);
		sysLogDao.setUserField1("Throwable : " + e2.getMessage());
		SysLogHome.getInstance().insertSysLog(sysLogDao);

	    System.out.println("Throwable error: " + e2.toString());
		e2.printStackTrace();
		return mapping.findForward(Constants.KEY_ACTION_MAPPING_ERR);
	}

	if (DEBUG) System.out.println(PROG_ID + "  : END nextPage="+nextPage);

	if(nextPage!=null){
		    System.out.println("@@@@@@@@@@strErrLogonMsg: " + strErrLogonMsg);
		if (DEBUG) System.out.println("mapping.findForward : nextPage="+nextPage);
	    return mapping.findForward(nextPage);
	}

	return mapping.findForward(Constants.KEY_ACTION_SUCCESS);
  }


}
